package dog.weatherwallpaper.model;

import android.content.Context;
import dog.weatherwallpaper.MainActivity;
import dog.weatherwallpaper.R;
import dog.weatherwallpaper.utils.App;
import dog.weatherwallpaper.utils.Internet;
import dog.weatherwallpaper.utils.Strings;

public enum WeatherInfo {
	INSTANCE;

	private Location location = new Location(null);
	private Weather weather = new Weather(null);

	private WeatherInfo() {
		if (App.containsPreference(R.string.location)) {
			this.location = new Location(App.getStringPreference(R.string.location));
		}
		if (App.containsPreference(R.string.weather)) {
			this.weather = new Weather(App.getStringPreference(R.string.weather));
		}
	}

	public static WeatherInfo getInstance() {
		return INSTANCE;
	}

	public boolean isOldWeather() {
		int updateInterval = App.getIntPreference(R.string.update_interval_key, R.string.update_interval_default);
		return this.weather.isOldInfo(updateInterval);
	}

	public boolean isOldWeather(final int hours) {
		return this.weather.isOldInfo(hours);
	}

	/**
	 * Updates the weather info (call only if Internet available and at least an
	 * hour after the last update).
	 * 
	 * @return true if updated, false if error.
	 */
	public boolean update() {
		final Internet i = new Internet();
		final String ip = i.getIP();
		if (Strings.isNullOrEmpty(ip)) { return false; }

		if (!ip.equals(App.getStringPreference(R.string.ip))) {
			final String location = i.getLocation(ip);
			if (Strings.isNullOrEmpty(location)) {
				return false;
			} else {
				this.location = new Location(location);
			}

			App.setStringPreference(R.string.ip, ip);
			App.setStringPreference(R.string.location, location);
		}

		final String weather = i.getWeather(ip);
		if (Strings.isNullOrEmpty(weather)) {
			return false;
		} else {
			this.weather = new Weather(weather);
		}
		App.setStringPreference(R.string.weather, weather);

		if (App.getBooleanPreference(R.string.notif_key)) {
			String changes = this.getChanges(this.weather);
			if (!Strings.isNullOrEmpty(changes)) {
				int icon = App.getIconId(this.weather.tomorrow().getIconName());
				String title = App.context().getString(R.string.notification_title);
				App.createNotification(icon, title, changes, MainActivity.class);
			}
		}

		return true;
	}

	/**
	 * @return weather info received from World Weather Online<br>
	 */
	public Weather getWeather() {
		return weather;
	}

	/**
	 * @return location received from Free Geo IP<br>
	 */
	public Location getLocation() {
		return location;
	}

	/**
	 * Looks for weather changes comparing today and tomorrow forecast.<br>
	 * Returns all changes found.<br>
	 * *
	 * <ol>
	 * <li>rain</li>
	 * <li>temperature drop</li>
	 * <li>temperature rise</li>
	 * </ol>
	 * 
	 * @return text containing changes, empty string if there aren't any.
	 */
	private String getChanges(Weather weather) {
		final int CELSIUS_VARIATION = 5;
		final int FAHRENHEIT_VARIATION = 9;

		String changes = "";
		Context c = App.context();

		double mm = weather.tomorrow().getPrecipMM();
		if (mm > 0) {
			changes += c.getString(R.string.rain) + ' ' + weather.tomorrow().getPrecipitation() + ". ";
		}

		boolean celsius = App.getBooleanPreference(R.string.temperature_key);
		if (celsius) {
			int min = weather.getTempMinCVariation();
			if (min >= CELSIUS_VARIATION) {
				changes += c.getString(R.string.min_temp_drop) + ' ' + min + c.getString(R.string.c) + ". ";
			}

			int max = weather.getTempMaxCVariation();
			if (max >= CELSIUS_VARIATION) {
				changes += c.getString(R.string.max_temp_rise) + ' ' + max + c.getString(R.string.c) + ". ";
			}
		} else {
			int min = weather.getTempMinFVariation();
			if (min > FAHRENHEIT_VARIATION) {
				changes += c.getString(R.string.min_temp_drop) + min + c.getString(R.string.f) + ". ";
			}

			int max = weather.getTempMaxFVariation();
			if (max > FAHRENHEIT_VARIATION) {
				changes += c.getString(R.string.max_temp_rise) + max + c.getString(R.string.f) + ". ";
			}
		}

		return changes;
	}
}